package com.gitee.wsl.struct.generator

import com.gitee.wsl.ext.base.isPrime
import com.gitee.wsl.lang.character.Ascii
import com.gitee.wsl.transform.encode.base.decodeBase64ToString


typealias GeneratorFun<T> = ()->T

typealias StringGenerator = GeneratorFun<String>

typealias IntGenerator = GeneratorFun<Int>

typealias LongGenerator = GeneratorFun<Long>

typealias FloatGenerator = GeneratorFun<Float>

typealias DoubleGenerator = GeneratorFun<Double>

typealias GeneratorWithLengthFun<T> = (length:Int)->T

typealias StringGeneratorWithLength = GeneratorWithLengthFun<String>

typealias ByteArrayGenerator = GeneratorFun<ByteArray>

fun stringIdGenerator(idPrefix: String=""): StringGenerator {
    var num = 0
    return { "$idPrefix${num++}" }
}

fun <T> Iterable<T>.withGeneratedIds(idPrefix: String, block: (id: String, item: T) -> Unit): List<String> {
    val generator = stringIdGenerator(idPrefix)
    return map { item -> generator().also { block(it, item) } }
}

object Generator {

    fun INT(base:Int):IntGenerator{
        var num = base
        return { num++ }
    }

    fun LONG(base:Long):LongGenerator{
        var num = base
        return { num++ }
    }

    fun FLOAT(base:Float):FloatGenerator{
        var num = base
        return { num++ }
    }

    fun DOUBLE(base:Double):DoubleGenerator{
        var num = base
        return { num++ }
    }

    fun BYTEARRAY(init:ByteArray):ByteArrayGenerator{
        return {init}
    }

    val DigitRandom: StringGeneratorWithLength = {length-> if (length == 0) "" else (1..length).map { ('0'..'9').random() }.joinToString("")}

    val LowercaseRandom: StringGeneratorWithLength = {length->(1..length).map { ('a'..'z').random() }.joinToString("")}

    val SpecialRandom : StringGeneratorWithLength ={length->
            if (length == 0) "" else (1..length).map {
                listOf('!', '@', '#', '$', '%', '&',
                    '*', '+', '=', '-', '~',
                    '?', '/', '_'
                ).random()
            }.joinToString("")
        }


    val UppercaseRandom: StringGeneratorWithLength ={length->if (length == 0) "" else (1..length).map { ('A'..'Z').random() }.joinToString("")}


    val Base64:StringGeneratorWithLength = { length->
        LowercaseRandom(length).decodeBase64ToString()
    }

    val ASCII:StringGeneratorWithLength = { length->
        (1..length).map { (Ascii.MIN..Ascii.MAX).random() }.joinToString("")
    }

    val Letter:StringGeneratorWithLength = { length ->
        (1..length).map { ('a'..'Z').random() }.joinToString("")
    }

    fun primeInt(start:Int):IntGenerator {
        val startGen = INT(start)
        return {
            var ret = startGen()
            while(!ret.isPrime()){ ret = startGen()}
            ret
        }
    }

    val FileName : StringGeneratorWithLength = {length->
        val size = length/3
        UppercaseRandom(size)+DigitRandom(size)+LowercaseRandom(length-size*2)
    }
}
